<template>
  <div class="MTable">
    <div class="actions flex mt-2 mb-4">
      <a-button type="primary" @click="handleAdd">新增</a-button>
      <a-button danger class="ml-3" @click="handleDelMutil">删除</a-button>

      <div v-if="isAllEdit">
        <a-button class="ml-3" @click="handleCancelAllEdit">返回</a-button>
      </div>
      <div class="flex-1 flex" v-else>
        <a-button class="ml-3" @click="handleAllEdit">批量编辑</a-button>
        <slot name="head"> </slot>
      </div>
    </div>
    <table class="my-table w-full">
      <thead class="thead">
        <th class="w-10">
          <Checkbox
            :disabled="!rawData.length"
            v-model:checked="checkAll"
            @change="onCheckAllChange"
            :indeterminate="indeterminate"
          />
        </th>
        <th class="w-15">序号</th>
        <template v-for="c in column" :key="c.label">
          <th :class="c.class">{{ c.label }}</th>
        </template>
        <th v-if="!isAllEdit" class="w-50">操作</th>
      </thead>

      <Draggable
        group="form-draggable"
        class="tbody"
        tag="tbody"
        :component-data="{
          tag: 'tbody',
          type: 'transition-group',
          name: 'list',
        }"
        ghostClass="moving"
        :animation="180"
        :list="rawData"
        handle=".th-drag"
        item-key="key"
        @update="handleSaveAllEdit"
      >
        <template #item="{ element: item, index }">
          <tr class="th-item">
            <td class="w-10"><Checkbox v-model:checked="item.check" /></td>
            <td class="w-15 th-drag"> <Icon icon="carbon:drag-vertical" /> {{ index + 1 }}</td>
            <template v-for="tbItem in column" :key="tbItem.label">
              <template v-if="isAllEdit">
                <td>
                  <template v-if="tbItem.component">
                    <div :class="['cell-item min-w-20', tbItem.class]">
                      <component
                        :is="tbItem.component"
                        v-model:value="item[tbItem.dataIndex]"
                        v-bind="
                          isFunction(tbItem.componentProps)
                            ? tbItem.componentProps({ data: item })
                            : tbItem.componentProps
                        "
                      />
                    </div>
                  </template>
                  <template v-else>
                    <div>
                      {{ item[tbItem.dataIndex] }}
                    </div>
                  </template>
                </td>
              </template>
              <template v-else>
                <td v-if="tbItem.format && isFunction(tbItem.format)">
                  {{ tbItem.format(item[tbItem.dataIndex], tbItem) }}
                </td>
                <td v-else>{{ item[tbItem.dataIndex] }} </td>
              </template>
            </template>
            <td v-if="!isAllEdit" class="w-50">
              <div class="actions">
                <a-button type="link" v-if="isCopy" @click.stop="handleCopy(item, index)"
                  >复制
                </a-button>
                <a-button type="link" v-if="getEdit" @click.stop="handleEdit(item, index)"
                  >编辑
                </a-button>
                <a-button
                  type="link"
                  v-if="showEvent && showEvent(item)"
                  @click.stop="handleEvent(item)"
                >
                  事件定义
                </a-button>
                <a-button type="link" danger @click.stop="handleDel(index)">删除</a-button>
              </div>
            </td>
          </tr>
        </template>
      </Draggable>
    </table>
  </div>
</template>

<script lang="ts">
  import { PropType, defineComponent, computed, ref, watch } from 'vue';
  import { Radio, Checkbox, Select, Input, InputNumber, Slider } from 'ant-design-vue';
  import { Icon } from '/@/components/Icon';
  import { IconPicker } from '/@/components/Icon';

  import { ApiRadioGroup } from '/@/components/Form';

  import { useMessage } from '/@/hooks/web/useMessage';
  import { isFunction, isBoolean } from '/@/utils/is';
  // import { cloneDeep } from 'lodash-es';

  import Draggable from 'vuedraggable';
  import { getDictTypeListApi } from '/@/api/admin/dict';
  import { DICT } from '/@/enums/dict';
  import { propTypes } from '/@/utils/propTypes';

  export default defineComponent({
    name: 'MTable',
    components: {
      Icon,
      RadioGroup: Radio.Group,
      ApiRadioGroup,
      Checkbox,
      Draggable,
      Select,
      Input,
      InputNumber,
      InputTextarea: Input.TextArea,
      Slider,
      IconPicker,
    },
    props: {
      data: {
        type: Array as PropType<Recordable[]>,
      },
      columns: {
        require: true,
        type: Array as PropType<Recordable[]>,
      },
      isEdit: propTypes.any,

      showEvent: propTypes.func,
      isCopy: propTypes.bool,
      showAllEdit: propTypes.bool,
    },
    emits: ['update:data', 'add', 'edit', 'copy', 'event'],
    setup(props, { emit }) {
      const { createMessage } = useMessage();
      const rawData = computed({
        get() {
          return props.data || [];
        },
        set(v) {
          return emit('update:data', v);
        },
      });
      const getEdit = computed(() => {
        if (isBoolean(props.isEdit)) return props.isEdit;
        return true;
      });

      const displayTypeList = ref<any[]>([]);
      if (!props.columns) {
        getDictTypeListApi({
          type: DICT.TABLE_BTN_LOCATION,
        }).then((res) => {
          if (displayTypeList.value.length <= 0) {
            res.forEach((el) => {
              el.value = el.intValue;
            });
            displayTypeList.value = res;
          }
        });
      }

      const column = [
        {
          label: '名称',
          dataIndex: 'label',
          component: 'Input',
          componentProps: {
            placeholder: '请输入名称',
          },
        },
        {
          label: '权限标识',
          dataIndex: 'code',
          component: 'Input',
          componentProps: {
            placeholder: '请输入名称',
          },
        },
        {
          label: '按钮位置',
          dataIndex: 'location',
          component: 'RadioGroup',
          class: '',
          componentProps: () => {
            return {
              options: displayTypeList.value,
            };
          },
          format(v) {
            const info = displayTypeList.value.find((el) => el.intValue === v);

            if (info) return info.label;
            return v;
          },
        },
        { label: '备注', dataIndex: 'remark' },
      ];

      const handleAdd = (record) => {
        emit('add', record);
      };
      const handleEdit = (record, index) => {
        record.index = index;
        emit('edit', record);
      };
      const handleCopy = (record, index) => {
        emit('copy', { record, index });
      };

      const handleDel = (index) => {
        rawData.value.splice(index, 1);
      };
      const handleDelMutil = () => {
        const arr = rawData.value || [];
        const data = arr.filter((el) => el.check);
        if (!data.length) {
          createMessage.warn('请先选择要删除的列');
          return;
        }
        if (data.length === arr.length) {
          checkAll.value = false;
        }

        rawData.value = arr.filter((el) => !el.check);
      };

      const checkAll = ref(false);
      watch(
        () => props.data,
        (v) => {
          if (!v) return;

          if (!v.length) {
            checkAll.value = false;
          } else {
            const arr = v.filter((el) => !el.check);
            checkAll.value = !arr.length;
          }
        },
        { deep: true },
      );

      const indeterminate = computed(() => {
        const arr = rawData.value || [];
        const len = arr.filter((el) => el.check).length;
        const allLen = arr.length;

        if (len === allLen) return false;
        return !!arr.find((el) => el.check);
      });

      const onCheckAllChange = (e) => {
        for (const item of rawData.value) {
          item.check = e.target.checked;
        }
      };

      const isAllEdit = ref(props.showAllEdit);
      const handleAllEdit = () => {
        if (!rawData.value.length) return createMessage.warning('暂无数据');
        isAllEdit.value = true;
      };
      const handleSaveAllEdit = () => {};
      const handleEvent = (item) => {
        emit('event', item);
      };
      const handleCancelAllEdit = () => {
        isAllEdit.value = false;
      };

      return {
        column: props.columns || column,
        indeterminate,
        checkAll,
        isAllEdit,
        rawData,
        getEdit,
        handleAdd,
        handleEdit,
        handleDel,
        handleDelMutil,
        isFunction,
        onCheckAllChange,
        handleAllEdit,
        handleCancelAllEdit,
        handleSaveAllEdit,
        handleEvent,
        handleCopy,
      };
    },
  });
</script>
<style lang="less" scoped>
  .my-table {
    text-align: left;
    table-layout: fixed;
    border-radius: 4px 4px 0 0;
    box-sizing: border-box;
    color: #666;
    border-collapse: separate;
    border-spacing: 0;

    th,
    td {
      padding: 12px 8px;
      overflow-wrap: break-word;
    }

    .thead {
      background: #edf3fc;
      box-shadow: 0px 4px 4px -3px #dde6f1, inset 0px 1px 4px -3px #35629a;
      border-bottom: 1px solid #bad3f1;
      white-space: nowrap;
      text-overflow: ellipsis;
      word-break: keep-all;
    }

    .th-item {
      font-size: 14px;
      font-weight: 400;
      color: #262626;

      &:hover {
        background: #f4f8ff;
        box-shadow: 0px 4px 4px -3px #e9edf3;
      }

      .th-drag {
        &:hover {
          cursor: grab;
          background: #edf3fc;
          box-shadow: 0px 4px 4px -3px #dde6f1, inset 0px 1px 4px -3px #35629a;
        }
      }
    }

    .actions {
      .ant-btn-link {
        padding: 0 4px;
      }
    }
  }
</style>
